package Ptolemaiosz;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.*;
import java.io.*;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.*;
import javax.swing.*;
 


/**
 * This class demonstrates how to load an Image from an external file
 */
public class Java2dtest extends Component {
           
    BufferedImage avatar;
    BufferedImage key;
    BufferedImage keyCollected;
    BufferedImage door;
    BufferedImage walltexture;
    BufferedImage background;
    BufferedImage backgroundFull;
    TexturePaint walltexturePaint;
    
    public int fps = 0;
    
    int LevelPartMargin = 40;
   
    //Modell
        //Referencia az application objektumra, hogy tugyjunk vele kommunikalni
        static Application application = null;  
        static Initializer initializer = null;  

    public void screenShot()
        {
            BufferedImage bi = new BufferedImage((int)this.getSize().getWidth(), (int)this.getSize().getHeight(), BufferedImage.TYPE_INT_ARGB);
            Graphics g = bi.createGraphics();
            
            paint(g);
            
         try{
                ImageIO.write(bi, "PNG", new File("shot" + Long.toString(System.currentTimeMillis()) + ".png"));
            }
            catch(Exception e){}
        }
        
    public void paint(Graphics g) {
        //Megfelelo kasztolas, valamiert kell
            Graphics2D g2 = (Graphics2D)g;
            
        //Beallitjuk, hogy a kitoltes fal textura legyen: 
            g2.setPaint(walltexturePaint);

        //Berakjuk az alaphatteret
        g2.drawImage(backgroundFull, 0, 0, (int)this.getSize().getWidth(), (int)this.getSize().getHeight(), this);
            
        //levelpartok lekerese    
        ArrayList<ArrayList<LevelPart>> neighbour2DArray = application.getLevelPartManager().getLevel().getneighbour2DArray();
        
        
        //Sorok szamanak meghatarozasa, ami azert nehezebb, mert eredetileg 10 ueres sor van es a nem uresek szama kell
                int numberOfRows = 0;
                
                for(int i = 0;i < neighbour2DArray.size();i++)
                    {
                        if(neighbour2DArray.get(i).size() != 0)
                            numberOfRows++;
                    }
                
        //Oszlopok szamanak a meghatarozasa
                int numberOfCols = neighbour2DArray.get(0).size();
                
       
        //Egy levelpart szelessegenek a meghatarozasa
        int LevelPartWidth  = (this.getSize().width  - (numberOfCols * 2 * LevelPartMargin)) / numberOfCols; 
        int LevelPartHeight = (this.getSize().height - (numberOfRows * 2 * LevelPartMargin)) / numberOfRows; 
                
        
        //Minden levelpart kirajzolasa
        for(int row = 0; row < numberOfRows; row++)
            {
                for(int col = 0 ;col < numberOfCols; col++)
                {
                    int paddignLeft = col * LevelPartWidth + LevelPartMargin + col * 2 * LevelPartMargin;
                    int paddignTop  = row * LevelPartHeight + LevelPartMargin + row * 2 * LevelPartMargin;
                    displayLevelPartToRectangle(neighbour2DArray.get(row).get(col), paddignLeft, paddignTop, LevelPartWidth, LevelPartHeight,g2);
                }
            }
        
        
        //Fps kirajzolasa a sarokba
        g2.setColor(Color.red);
        g2.drawString("FPS: " + Float.toString(fps), 10, 20);
        
    }
 
    //Szikseges eroforrasok betoltese es eloallitasa
    public Java2dtest() {
       try {
           avatar = ImageIO.read(new File("images/avatar.png"));
           key = ImageIO.read(new File("images/key.png"));
           keyCollected = ImageIO.read(new File("images/key_collected.png"));
           door = ImageIO.read(new File("images/door.png"));
           walltexture = ImageIO.read(new File("images/wall_texture.jpg"));
           background = ImageIO.read(new File("images/background.jpg"));
           backgroundFull = ImageIO.read(new File("images/background_full.jpg"));
           
           walltexturePaint = new TexturePaint(walltexture, new Rectangle2D.Double(0, 0, walltexture.getWidth(), walltexture.getHeight()));
       } catch (IOException e) {
       }
 
    }
 
    //Ablak meretenek beallitasa
    public Dimension getPreferredSize() {
           
           return new Dimension(1200, 600);

    }
 
    public static void main(String[] args) {
        
        //Modell
            //Application letrehozasa
            application = new Application();
            
            //Initializer letrehozasa aki ismeri az applicationt
            initializer = new Initializer();
            initializer.setApplication(application);
            
            //Uj levelpartmanager, s megtanitas az applicationnak
            application.setLevelPartManager(new LevelPartManager());
            //Uj Initilaizer, s megtanitas az applicationnak
            application.setInitializer(initializer);
            //Uj Physics, s megtanitas az applicationnak
            application.setPhysics(new Physics());   
          
            initializer.loadLevel(1);
        //Modell vege
        
 
        JFrame f = new JFrame("Ptolemaiosz");
             
        f.addWindowListener(new WindowAdapter(){
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });
 
        final Java2dtest instance = new Java2dtest();
        
        f.add(instance);
        f.pack();
        f.setVisible(true);
        f.createBufferStrategy(2);
        
        KeyListener listener = new KeyListener() {

            @Override
            public void keyTyped(KeyEvent e) {
               
            }

            @Override
            public void keyPressed(KeyEvent e) {
                //throw new UnsupportedOperationException("Not supported yet.");
                if (e.getKeyChar() == 'p')
                    {
                        instance.screenShot();
                    }
                
                
               if (e.getKeyChar() == 'w')
                    {
                        //Majd o ellenorzi mozaik nezetben van-e
                        application.moveLevelPart(Direction.up);

                        //Majd o ellenorzi jatekos nezetben van-e
                        application.moveAvatar(Direction.up, 1);
                    }
                
              if (e.getKeyChar() == 'a')
                    {
                        //Majd o ellenorzi mozaik nezetben van-e
                        application.moveLevelPart(Direction.left);

                        //Majd o ellenorzi jatekos nezetben van-e
                        application.moveAvatar(Direction.left, 1);
                    }
            
             if (e.getKeyChar() == 'd')
                    {
                        //Majd o ellenorzi mozaik nezetben van-e
                        application.moveLevelPart(Direction.right);

                        //Majd o ellenorzi jatekos nezetben van-e
                        application.moveAvatar(Direction.right, 1);
                    }
             
            if (e.getKeyChar() == 's')
                    {
                        //Majd o ellenorzi mozaik nezetben van-e
                        application.moveLevelPart(Direction.down);
                    }
             
            if (e.getKeyChar() == 'i')
                    {
                        //Majd o ellenorzi mozaik nezetben van-e
                        application.moveLevelPart(Direction.up);

                        //Majd o ellenorzi jatekos nezetben van-e
                        application.moveAvatar(Direction.up, 2);
                    }
                
              if (e.getKeyChar() == 'j')
                    {
                        //Majd o ellenorzi mozaik nezetben van-e
                        application.moveLevelPart(Direction.left);

                        //Majd o ellenorzi jatekos nezetben van-e
                        application.moveAvatar(Direction.left, 2);
                    }
            
             if (e.getKeyChar() == 'l')
                    {
                        //Majd o ellenorzi mozaik nezetben van-e
                        application.moveLevelPart(Direction.right);

                        //Majd o ellenorzi jatekos nezetben van-e
                        application.moveAvatar(Direction.right, 2);
                    }
             
             
            if (e.getKeyChar() == 'r')
                    {
                        application.restartLevel();
                    }
            
           if (e.getKeyChar() == 'n')
                    {
                        application.nextLevel();
                    }
           
          if (e.getKeyChar() == ' ')
                    {
                        application.chageViewMode();
                    }
                
            }

            @Override
            public void keyReleased(KeyEvent e) {
                //throw new UnsupportedOperationException("Not supported yet.");
                
            }
        };
        
        f.addKeyListener(listener);
        
        
        
        long lastTime = System.currentTimeMillis();
        
        while(true)
            {
            try {
                long currentTime = System.currentTimeMillis();
                long deltaTime = currentTime - lastTime;
                
                application.getPhysics().update((int) (deltaTime) ); 
                
                    //Calculate fps
                        if((deltaTime) != 0)
                            instance.fps =  (int) (1000 / deltaTime);
                    
                    //upgrade last time
                    lastTime = currentTime;
                
             BufferStrategy bf = f.getBufferStrategy();
             Graphics g = bf.getDrawGraphics();
                  
             f.paint(g);
             g.dispose();
             
             // Shows the contents of the backbuffer on the screen.
             bf.show();
             //Tell the System to do the Drawing now, otherwise it can take a few extra ms until 
              Toolkit.getDefaultToolkit().sync();
                
            } catch (Exception ex) {
                Logger.getLogger(Java2dtest.class.getName()).log(Level.SEVERE, null, ex);
            }
            }
         
    }
    
    
    
    
    protected void displayLevelPartToRectangle(LevelPart levelpart, int x, int y, int width, int height, Graphics2D canvas)
        {
            
            canvas.drawImage(background, x, y, width, height, null);
            
            //Fizikai entitasok lekerese
            ArrayList<PhysicalEntity> PhysicalEntites = application.getLevelPartManager().getLevel().getPhysicalEntities(levelpart);
            
            //###############################
            //##    Minden falra
            //###############################
            
            for(int i = 0; i < PhysicalEntites.size();i++)
                {
                    if(PhysicalEntites.get(i).getClass().getName().equals("Ptolemaiosz.WallPhysicalEntity"))
                    {
                        PhysicalEntity wall = PhysicalEntites.get(i);
                        
                        //Fal poligonjanak lekerese
                        ArrayList<Vector> vertexes  = wall.getPolygon().getVertexes();
                        
                        //Kirajzolando poligon letrehozasa
                        Polygon canvasPolygon = new Polygon();
                       
                        //Kirajzolando polygon feltoltese, at transzformalt elemekkel
                            for(int j = 0; j < vertexes.size();j++)
                                {
                                    Vector displayVector = new Vector();
                                        displayVector.add(vertexes.get(j)); //Hozzaadjuk a csucsot
                                        displayVector.add(wall.position); //Hozzadjuk a kozeppontot, igy a palyaszakszon belul mar abszolut lesz
                                        
                                        //Mas a koordinata rendszer at kell konvertalni
                                        displayVector.setY(100.0f - displayVector.getY());
                                        
                                        //Fel kell skalazni az uj meretre
                                            float widthFactor  = width  / 100.0f;
                                            float heightFactor = height / 100.0f;

                                            displayVector.setX(displayVector.getX() * widthFactor);
                                            displayVector.setY(displayVector.getY() * heightFactor);
                                                
                                        //el kell tolni a megfelelo pozicioba a kepet
                                        displayVector.add(new Vector(x, y));
                                            
                                    //Majd belerakni a vegleges poligonba
                                    canvasPolygon.addPoint((int) displayVector.getX(),(int) displayVector.getY());
                                }
                        
                        //Ki kell rajzolni a vegleges poligont
                        canvas.fillPolygon(canvasPolygon);
                    }
                }
            
            //###############################
            //##    Minden Avatarra
            //###############################
            
            for(int i = 0; i < PhysicalEntites.size();i++)
                {
                    if(PhysicalEntites.get(i).getClass().getName().equals("Ptolemaiosz.AvatarPhysicalEntity"))
                    {
                        PhysicalEntity wall = PhysicalEntites.get(i);
                        
                        //Fal poligonjanak lekerese
                        ArrayList<Vector> vertexes  = wall.getPolygon().getVertexes();
                        
                        //Kirajzolando poligon letrehozasa
                        Polygon canvasPolygon = new Polygon();
                       
                        //Kirajzolando polygon feltoltese, at transzformalt elemekkel
                            for(int j = 0; j < vertexes.size();j++)
                                {
                                    Vector displayVector = new Vector();
                                        displayVector.add(vertexes.get(j)); //Hozzaadjuk a csucsot
                                        displayVector.add(wall.position); //Hozzadjuk a kozeppontot, igy a palyaszakszon belul mar abszolut lesz
                                        
                                        //Mas a koordinata rendszer at kell konvertalni
                                        displayVector.setY(100.0f - displayVector.getY());
                                        
                                        //Fel kell skalazni az uj meretre
                                            float widthFactor  = width  / 100.0f;
                                            float heightFactor = height / 100.0f;

                                            displayVector.setX(displayVector.getX() * widthFactor);
                                            displayVector.setY(displayVector.getY() * heightFactor);
                                                
                                        //el kell tolni a megfelelo pozicioba a kepet
                                        displayVector.add(new Vector(x, y));
                                            
                                    //Majd belerakni a vegleges poligonba
                                    canvasPolygon.addPoint((int) displayVector.getX(),(int) displayVector.getY());
                                }
                        
                        //Ki kell rajzolni a vegleges poligont  
                        canvas.drawImage(avatar,canvasPolygon.xpoints[3],canvasPolygon.ypoints[3], canvasPolygon.xpoints[1] - canvasPolygon.xpoints[0],canvasPolygon.ypoints[1] - canvasPolygon.ypoints[2], this);
                    }
                }
            
            
            //###############################
            //##    Minden kulcsra
            //###############################
            
            for(int i = 0; i < PhysicalEntites.size();i++)
                {
                    if(PhysicalEntites.get(i).getElement().getClass().getName().equals("Ptolemaiosz.Key"))
                    {
                        PhysicalEntity wall = PhysicalEntites.get(i);
                        
                        //Fal poligonjanak lekerese
                        ArrayList<Vector> vertexes  = wall.getPolygon().getVertexes();
                        
                        //Kirajzolando poligon letrehozasa
                        Polygon canvasPolygon = new Polygon();
                       
                        //Kirajzolando polygon feltoltese, at transzformalt elemekkel
                            for(int j = 0; j < vertexes.size();j++)
                                {
                                    Vector displayVector = new Vector();
                                        displayVector.add(vertexes.get(j)); //Hozzaadjuk a csucsot
                                        displayVector.add(wall.position); //Hozzadjuk a kozeppontot, igy a palyaszakszon belul mar abszolut lesz
                                        
                                        //Mas a koordinata rendszer at kell konvertalni
                                        displayVector.setY(100.0f - displayVector.getY());
                                        
                                        //Fel kell skalazni az uj meretre
                                            float widthFactor  = width  / 100.0f;
                                            float heightFactor = height / 100.0f;

                                            displayVector.setX(displayVector.getX() * widthFactor);
                                            displayVector.setY(displayVector.getY() * heightFactor);
                                                
                                        //el kell tolni a megfelelo pozicioba a kepet
                                        displayVector.add(new Vector(x, y));
                                            
                                    //Majd belerakni a vegleges poligonba
                                    canvasPolygon.addPoint((int) displayVector.getX(),(int) displayVector.getY());
                                }
                        
                        //Ki kell rajzolni a vegleges poligont 
                         Key key1 = (Key) wall.getElement();
                         
                         if(key1.getCollected())                             
                            canvas.drawImage(keyCollected,canvasPolygon.xpoints[3],canvasPolygon.ypoints[3], canvasPolygon.xpoints[1] - canvasPolygon.xpoints[0],canvasPolygon.ypoints[1] - canvasPolygon.ypoints[2], this);
                         else
                            canvas.drawImage(key,canvasPolygon.xpoints[3],canvasPolygon.ypoints[3], canvasPolygon.xpoints[1] - canvasPolygon.xpoints[0],canvasPolygon.ypoints[1] - canvasPolygon.ypoints[2], this);
                    }
                }
            
            //###############################
            //##    Minden Ajtora
            //###############################
            
            for(int i = 0; i < PhysicalEntites.size();i++)
                {
                    if(PhysicalEntites.get(i).getElement().getClass().getName().equals("Ptolemaiosz.Door"))
                    {
                        PhysicalEntity wall = PhysicalEntites.get(i);
                        
                        //Fal poligonjanak lekerese
                        ArrayList<Vector> vertexes  = wall.getPolygon().getVertexes();
                        
                        //Kirajzolando poligon letrehozasa
                        Polygon canvasPolygon = new Polygon();
                       
                        //Kirajzolando polygon feltoltese, at transzformalt elemekkel
                            for(int j = 0; j < vertexes.size();j++)
                                {
                                    Vector displayVector = new Vector();
                                        displayVector.add(vertexes.get(j)); //Hozzaadjuk a csucsot
                                        displayVector.add(wall.position); //Hozzadjuk a kozeppontot, igy a palyaszakszon belul mar abszolut lesz
                                        
                                        //Mas a koordinata rendszer at kell konvertalni
                                        displayVector.setY(100.0f - displayVector.getY());
                                        
                                        //Fel kell skalazni az uj meretre
                                            float widthFactor  = width  / 100.0f;
                                            float heightFactor = height / 100.0f;

                                            displayVector.setX(displayVector.getX() * widthFactor);
                                            displayVector.setY(displayVector.getY() * heightFactor);
                                                
                                        //el kell tolni a megfelelo pozicioba a kepet
                                        displayVector.add(new Vector(x, y));
                                            
                                    //Majd belerakni a vegleges poligonba
                                    canvasPolygon.addPoint((int) displayVector.getX(),(int) displayVector.getY());
                                }
                        
                        //Ki kell rajzolni a vegleges poligont  
                        canvas.drawImage(door,canvasPolygon.xpoints[3],canvasPolygon.ypoints[3], canvasPolygon.xpoints[1] - canvasPolygon.xpoints[0],canvasPolygon.ypoints[1] - canvasPolygon.ypoints[2], this);
                    }
                }
        }
}